package com.health.trans.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import com.health.trans.channel.MemorySet;
import com.health.trans.common.util.GenericUtil;
import com.health.trans.service.action.AppendChildDataAction;
import com.health.trans.service.action.ChildData;
import com.health.trans.service.action.TransAction;
import com.health.trans.util.CacheMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;

/**
 * @author nqlz
 */
@Component
public class AsyncDataService {

    public static final CacheMap<Class<?>, TransAction<Object, Object>> TRANS_ACTION_MAP = new CacheMap<>();
    public static CacheMap<Class<?>, MemorySet> channelMap = new CacheMap<>();

    @Autowired
    private CorrelationService correlationService;

    public void init() {
        //添加自定义类Action
        ClassUtil.scanPackage("com.health.trans.service.action")
                .stream()
                .map(i -> {
                    Object o = null;
                    try {
                        o = ReflectUtil.newInstance(i, correlationService);
                    } catch (UtilException ignored) {
                    }
                    return o;
                })
                .filter(Objects::nonNull)
                .map(i -> (TransAction<Object, Object>) i)
                .filter(i -> Objects.nonNull(i.getTClass()))
                .forEach(i -> TRANS_ACTION_MAP.put(i.getTClass(), i));

        //公共添加子表数据类
        for (Class<?> childClass : ChildData.appendChildClasses) {
            TRANS_ACTION_MAP.put(childClass, AppendChildDataAction.instance(GenericUtil.get(childClass), correlationService));
        }
    }

    public <T, J> TransAction<T, J> syncData(List<T> objects) {
        if (MapUtil.isEmpty(TRANS_ACTION_MAP)) {
            init();
        }
        if (CollUtil.isEmpty(objects)) {
            return null;
        }
        Class<T> tClass = ClassUtil.getClass(objects.get(0));

        TransAction<T, J> transAction = getTransAction(tClass);

        objects.parallelStream().forEach(transAction::transData);
        return transAction;
    }

    public <T, J> TransAction<T, J> getTransAction(Class<T> tClass) {
        return GenericUtil.get(TRANS_ACTION_MAP.get(tClass, () -> {
            TransAction<T, J> instance = TransAction.instance(tClass, correlationService);
            TRANS_ACTION_MAP.put(tClass, GenericUtil.get(instance));
            return GenericUtil.get(instance);
        }));
    }

    /**
     * 一个类一个通道 获得内存通道
     *
     * @return {@link MemorySet}
     */
    public static MemorySet getChannel(Class<?> tClass) {
        return channelMap.get(tClass);
    }

    public static MemorySet initChannel(Class<?> tClass, Consumer<?> lineHandler) {
        return channelMap.get(tClass, () -> {
            MemorySet channel = new MemorySet();
            channel.setLineHandler(lineHandler);
            channelMap.put(tClass, channel);
            return channel;
        });
    }
}
